package com.hzw.saas.service.hpc.service.impl;

import cn.hutool.core.map.MapUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpStatus;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.hzw.saas.api.hpc.IHpcAccountProviderService;
import com.hzw.saas.api.hpc.bo.HpcAccountBo;
import com.hzw.saas.api.hpc.bo.HpcAccountProviderBo;
import com.hzw.saas.api.hpc.bo.HpcAccountRecordBo;
import com.hzw.saas.common.util.Json;
import com.hzw.saas.service.hpc.data.HACDetail;
import com.hzw.saas.service.hpc.response.ProviderUser;
import com.hzw.saas.service.hpc.service.AbstractHpcFetchService;
import jodd.util.StringUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 通过并行接口拉取的超算明细（临时后期删除）
 * </p>
 *
 * @author sonam
 * @since 2021/3/23 15:07
 */
@Slf4j
@Service("hpcFetchServiceImpl")
public class HpcFetchServiceImpl extends AbstractHpcFetchService {

    @Resource(name = "hpcAccountProviderServiceImpl")
    private IHpcAccountProviderService providerService;

    /**
     * 远程拉取HPC明细，并转为特定的数据格式的HPCDetail
     *
     * @param hpcAccountRecordBo
     * @param startDateStr
     * @param endDateStr
     * @return
     */
    @Override
    protected List<HACDetail> fetchHpcDetails(HpcAccountRecordBo hpcAccountRecordBo, String startDateStr, String endDateStr) {
        String hpcAccountId = hpcAccountRecordBo.getHpcAccountId();
        HpcAccountBo hpcAccountBo = hpcAccountService.getById(hpcAccountId);

        String providerId = hpcAccountBo.getProviderId();
        HpcAccountProviderBo hpcAccountProviderBo = providerService.getById(providerId);

        String userName = hpcAccountProviderBo.getUserName();
        String password = hpcAccountProviderBo.getPassword();
        String providerName = hpcAccountProviderBo.getProviderName();

        log.debug("开始查询供应商({})下，账号({})中的超算账号的使用明细", providerName, userName);
        String token = doLogin(userName, password);

        if (StringUtil.isBlank(token)) {
            log.warn("查询供应商({})下，账号({})失败", providerName, userName);
            return new ArrayList<>();
        }
        // 获取当前账号下的所有超算账号使用明细
        List<HACDetail> details = doGetAccountDetailList(token, doGetAccountList(token), startDateStr, endDateStr);

        if (CollectionUtils.isEmpty(details)) {
            log.debug("供应商({})，{} - {}没有超算明细数据!", providerName, startDateStr, endDateStr);
        }

        return details;
    }

    /**
     * 登录
     *
     * @param userName
     * @param password
     * @return
     */
    private String doLogin(String userName, String password) {
        password = DigestUtil.md5Hex(password);
        Map<String, Object> params = MapUtil.builder(new HashMap<String, Object>())
            .put("email", userName)
            .put("password", password)
            .put("token_type", "TOKEN")
            .put("third_party", "SELF").build();
        HttpRequest httpRequest = HttpUtil.createPost("https://user.paratera.com/user/api/login");
        httpRequest.form(params);
        HttpResponse httpResponse = httpRequest.execute();
        String paraToken = httpResponse.header("PARA_TOKEN");
        return paraToken;
    }

    /**
     * 获取用户列表
     *
     * @param token
     * @return
     */
    @SneakyThrows
    private ProviderUser doGetAccountList(String token) {
        HttpRequest httpRequest = HttpUtil.createGet("https://user.paratera.com/user/api/query?token_type=TOKEN&winfo=true");
        httpRequest.header("para_token", token);
        HttpResponse httpResponse = httpRequest.execute();
        String body = httpResponse.body();
        return Json.parseObject(body, ProviderUser.class);
    }

    /**
     * 获取超算列表信息
     *
     * @param token
     * @param user
     * @param startDate
     * @param endDate
     * @return
     */
    @SneakyThrows
    private List<HACDetail> doGetAccountDetailList(String token, ProviderUser user, String startDate, String endDate) {
        List<HACDetail> details = new ArrayList<>();

        String api = "https://billing.paratera.com/billing/api/jobs/list";
        String url = String.format("%s?uid=%s&beginDay=%s&endDay=%s&pageNO=%d&pageSize=%d&npi=1",
            api, user.getUserId(),
            startDate, endDate, 1, Integer.MAX_VALUE);
        HttpRequest httpRequest = HttpUtil.createGet(url);
        httpRequest.header("para_token", token);
        HttpResponse httpResponse = httpRequest.execute();

        if (httpResponse.getStatus() != HttpStatus.HTTP_OK) {
            return details;
        }

        String body = httpResponse.body();
        JsonNode jsonNode = Json.parseJson(body);
        JsonNode jobs = jsonNode.get("jobs");
        try {
            details.addAll(JSONUtil.parseArray(jobs.toString()).toList(HACDetail.class));
        } catch (Exception e) {
            log.error("parsing detail json error", e);
        }

        log.info(user.getEmail() + user.getUserId() + ": " + details.size());
        return details;
    }

}
